"""
使用延迟计算属性

问题：
    你想将一个只读属性定义成一个property，并且只在访问的时候才会计算结果。
     但是一旦被访问后，你希望结果值被缓存起来，不用每次都去计算。
解决方案：
    定义一个延迟属性的一种高效方法是通过使用一个描述器类。
"""

import math


class LazyProperty:
    def __init__(self, func):
        self.func = func

    def __get__(self, instance, owner):
        if instance is None:
            return self
        else:
            value = self.func(instance)
            setattr(instance, self.func.__name__, value)
            return value


class Circle:
    def __init__(self, radius):
        self.radius = radius

    @LazyProperty
    def area(self):
        print("计算面积")
        return math.pi * self.radius ** 2

    @LazyProperty
    def perimeter(self):
        print("计算周长")
        return 2 * math.pi * self.radius


def use_circle():
    circle = Circle(2)
    print(circle.area)
    print(circle.area)
    print(circle.perimeter)
    print(circle.perimeter)
    # 输出结果：
    """
    计算面积
    12.566370614359172
    12.566370614359172
    计算周长
    12.566370614359172
    12.566370614359172
    """


if __name__ == '__main__':
    use_circle()
